package net.xo68.destiny.core.rocksdb;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;

import java.nio.charset.Charset;

public class GenericJackson2JsonRocksValueSerializer<T> implements RocksSerializer<T> {

    private final JavaType javaType;

    private final ObjectMapper mapper;

    private Charset charset=Charset.defaultCharset();

    public GenericJackson2JsonRocksValueSerializer(Class<T> type) {
        this(new ObjectMapper(),type);
    }
    public GenericJackson2JsonRocksValueSerializer(ObjectMapper mapper,Class<T> type) {
        this.mapper = mapper;
        this.javaType=getJavaType(type);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
    }

    public Charset getCharset() {
        return charset;
    }

    public void setCharset(Charset charset) {
        this.charset = charset;
    }

    @Override
    public byte[] serialize(T t) throws RocksSerializationException {
        if (t == null) {
            return new byte[0];
        }

        try {
            return mapper.writeValueAsBytes(t);
        } catch (JsonProcessingException e) {
            throw new RocksSerializationException("Could not write JSON: " + e.getMessage(), e);
        }
    }

    @Override
    public T deserialize(byte[] bytes) throws RocksSerializationException {
        if (bytes==null || bytes.length==0) {
            return null;
        }
        try {
            return (T) this.mapper.readValue(bytes, 0, bytes.length, javaType);
        } catch (Exception ex) {
            throw new RocksSerializationException("Could not read JSON: " + ex.getMessage(), ex);
        }
    }


    protected JavaType getJavaType(Class<?> clazz) {
        return TypeFactory.defaultInstance().constructType(clazz);
    }
}
